package com.zer0.tga.level;

import java.util.ArrayList;
import java.util.List;

import com.zer0.tga.art.Screen;
import com.zer0.tga.entity.Entity;
import com.zer0.tga.level.RoomGenerator.RoomInfo;
import com.zer0.tga.math.BoundingBox;
import com.zer0.tga.math.Coordinate;
import com.zer0.tga.math.Direction;
import com.zer0.tga.math.RandNum;
import com.zer0.tga.tile.GrassTile;
import com.zer0.tga.tile.HoleTile;
import com.zer0.tga.tile.Tile;
import com.zer0.tga.tile.WallTile;
import com.zer0.tga.entity.abstractentity.BossStarter;
import com.zer0.tga.entity.abstractentity.ShopStarter;
import com.zer0.tga.entity.abstractentity.Teleporter;
import com.zer0.tga.entity.livingentity.LivingEntity;
import com.zer0.tga.entity.livingentity.Teemo;
import com.zer0.tga.entity.livingentity.mob.*;
/*import com.zer0.tga.entity.livingentity.mob.BoomerangBlade;
import com.zer0.tga.entity.livingentity.mob.CasterMinion;
import com.zer0.tga.entity.livingentity.mob.GiantWolf;
import com.zer0.tga.entity.livingentity.mob.RedWraith;
import com.zer0.tga.entity.livingentity.mob.Wolf;
import com.zer0.tga.entity.livingentity.mob.Wraith;
*/
public class Room {
	
	public enum RoomType{ NORMAL_ROOM, START_ROOM, BOSS_ROOM, SHOP_ROOM } 
	
	public RoomType roomType;
	
	public int mobCount;
	
	public boolean hasNorthDoor;
	public boolean hasSouthDoor;
	public boolean hasEastDoor;
	public boolean hasWestDoor;
	
	//public Tile[] tiles;
   // public List<Entity>[] entityMap;
    public List<Entity> entities = new ArrayList<Entity>();
    
    public boolean doorsOpen = false; 
    
    public boolean minimap_wasHere = false;
    public boolean minimap_canSee = false;
    
    
    public int roomID;
	
    
	public Tile RoomInterior[]; // interior crocodile alligator, i drive a chevrolet movie theather
	
	public static int ROOM_X = 13;
	public static int ROOM_Y = 9;
	
	public static int ROOM_NORTHDOOR = ((ROOM_X+1)/2)-1;
	public static int ROOM_SOUTHDOOR = (ROOM_X*ROOM_Y)-ROOM_NORTHDOOR-1;
	public static int ROOM_WESTDOOR = ROOM_X*(ROOM_Y-1)/2;
	public static int ROOM_EASTDOOR = (ROOM_X*(ROOM_Y+1)/2)-1;
	
	
	public Level level;
	
	public Room(Level level){
		//init();
		//this.roomType = RoomType.NORMAL_ROOM;
		this(level,RoomType.NORMAL_ROOM);		
		this.level = level;
	
	}
	
	public Room(Level level,RoomType rt)
	{
		init();
		this.roomType = rt;
		this.level = level;
		RoomInfo room = RoomGenerator.getInstance().getRandomRoom(level, roomType);
		
		if(rt == RoomType.SHOP_ROOM)
		{
			ShopStarter ss = new ShopStarter(new Coordinate(Room.ROOM_X*Tile.WIDTH/2,Room.ROOM_Y*Tile.HEIGHT/2), new Coordinate (16,16));
			addEntity(ss);
		}
		else if(rt == RoomType.BOSS_ROOM)
		{
			BossStarter bs = new BossStarter(new Coordinate(Room.ROOM_X*Tile.WIDTH/2,Room.ROOM_Y*Tile.HEIGHT/2), new Coordinate (32,32));
			addEntity(bs);
		}
		
		prepareRoom(room);
		//entityMap = new List[ROOM_X*ROOM_Y];
	}

	private void prepareRoom(RoomInfo room) {
		// TODO Auto-generated method stub

		// prepare tiles
		for(int i=0;i<room.RoomInterior.length;i++)
		{
			if (room.RoomInterior[i] == 0)
			{
				RoomInterior[i] = new WallTile();
				RoomInterior[i].setSide(Direction.NORTH);
			}
			else if(room.RoomInterior[i] == 1)
			{
				RoomInterior[i] = new WallTile();
				RoomInterior[i].setSide(Direction.EAST);

			}
			else if(room.RoomInterior[i] == 2)
			{
				RoomInterior[i] = new WallTile();
				RoomInterior[i].setSide(Direction.SOUTH);
			}
			else if(room.RoomInterior[i] == 3)
			{
				RoomInterior[i] = new WallTile();
				RoomInterior[i].setSide(Direction.WEST);
			}
			else if(room.RoomInterior[i] == 4)
			{
				RoomInterior[i] = new GrassTile();
			}
			else if(room.RoomInterior[i] == 5)
			{
				RoomInterior[i] = new HoleTile();
			}

			RoomInterior[i].init(level, (i%Room.ROOM_X), (i/Room.ROOM_X));

		}

		// get the id
		roomID = room.roomID;

		// prepare mobs
		if(room.MobPool.size() != 0)
		{
			String mobs = room.MobPool.get(RandNum.getRandNum(0, room.MobPool.size()));

			for(int i = 0; i<mobs.length(); i++)
			{
				char mobType = mobs.charAt(i);
				if(mobType == 'A')
					this.addMob(new CasterMinion());
				else if(mobType == 'B')
					this.addMob(new Wolf());
				else if(mobType == 'C')
					this.addMob(new GiantWolf());
				else if(mobType == 'D')
					this.addMob(new RedWraith());
				else if(mobType == 'E')
					this.addMob(new Wraith());
				else if(mobType == 'F')
					this.addMob(new BoomerangBlade());
				else if(mobType == 'G')
					this.addMob(new MeleeMinion());
				
				
				// the rest
			}
		}
	}

	public void init()
	{
		this.mobCount = 0;
		
		this.hasNorthDoor = false;
		this.hasSouthDoor = false;
		this.hasEastDoor = false;
		this.hasWestDoor = false;
		
		RoomInterior = new Tile[ROOM_X*ROOM_Y];
	}
	public void tick() {
		// TODO Auto-generated method stub
		
		
		// tick for all entities in the room
		 for(int i=0;i<entities.size();i++)
		 {
			 Entity e = entities.get(i);
	            if (!e.removed) {
	                e.tick();
	                if(e.removed)
	                	entities.remove(e);
	            }
	            else
	            {
	            	entities.remove(e);
	            	//i--;
	            }      	
	         }
	}
	

	public void addEntity(Entity e) 
	{
       entities.add(e);
     //  System.out.println("Entity added: " + e.getClass().getSimpleName() + " to " + e.position.x + "," +e.position.y);
	}
	
	public void removeEntity(Entity e)
	{
		e.removed = true;
	  //  System.out.println("Entity removed: " + e.getClass().getSimpleName() + " from " + e.position.x + "," +e.position.y);   
	}
	
	public void addPlayerToRoom(Entity e) 
	{
       entities.add(e);
       minimap_wasHere = true;
      // System.out.println("Player added: " + e.getClass().getSimpleName() + " to " + e.position.x + "," +e.position.y);
	}
	
	public Entity removePlayerFromRoom()
	{
		//e.removed = true;
	    for(Entity e:entities)
	    {
	    	if (e instanceof Teemo)
	    	{
	    		entities.remove(e);
	    //	    System.out.println("Player removed: " + e.getClass().getSimpleName() + " from " + e.position.x + "," +e.position.y);   
	    		return e;
	    	}
	    	
	    }
	    return null;
	    
	}
	
	

    public List<BoundingBox> getBoundingBoxList(Entity e) {
        List<BoundingBox> result = new ArrayList<BoundingBox>();
        
        // Adding near tiles to list
        
        
        // x,y = (i%Room.ROOM_X), (i/Room.ROOM_X)
        
        //finding which tile the Entity e is on
        Coordinate currentTile = new Coordinate();
        currentTile.x = e.position.getX()/Tile.WIDTH;
        currentTile.y = e.position.getY()/Tile.HEIGHT;
        
        //adding adjacent tiles to list
        /*
        RoomInterior[(currentTile.x+1) + (currentTile.y+1) * ROOM_X].addBoundingBoxToList(result, e);
        RoomInterior[(currentTile.x+1) + (currentTile.y-1) * ROOM_X].addBoundingBoxToList(result, e);
        RoomInterior[(currentTile.x+1) + (currentTile.y  ) * ROOM_X].addBoundingBoxToList(result, e);
        RoomInterior[(currentTile.x-1) + (currentTile.y+1) * ROOM_X].addBoundingBoxToList(result, e);
        RoomInterior[(currentTile.x-1) + (currentTile.y-1) * ROOM_X].addBoundingBoxToList(result, e);
        RoomInterior[(currentTile.x-1) + (currentTile.y  ) * ROOM_X].addBoundingBoxToList(result, e);
        RoomInterior[(currentTile.x  ) + (currentTile.y+1) * ROOM_X].addBoundingBoxToList(result, e);
        RoomInterior[(currentTile.x  ) + (currentTile.y-1) * ROOM_X].addBoundingBoxToList(result, e);
        */
        for (int i=-1 ; i<=1 ; i++)
        {
        	if(currentTile.x+i<=-1 || currentTile.x+i>=ROOM_X)
        		continue;
        	for(int j=-1 ; j<=1 ; j++ )
        	{
        		if(currentTile.y+j<=-1 || currentTile.y+j>=ROOM_Y)
            		continue;
        		
        		 RoomInterior[(currentTile.getX()+i) + (currentTile.getY()+j) * ROOM_X].addBoundingBoxToList(result, e);   
        	}
        }
        	
        
      /*  BoundingBox bb = e.getBoundingBox().grow(Tile.WIDTH>Tile.HEIGHT ? Tile.WIDTH : Tile.HEIGHT);
        int x0 = (int) (bb.box.x0 / Tile.WIDTH);
        int x1 = (int) (bb.box.x1 / Tile.WIDTH);
        int y0 = (int) (bb.box.y0 / Tile.HEIGHT);
        int y1 = (int) (bb.box.y1 / Tile.HEIGHT);

        for (int y = y0; y <= y1; y++) {
            if (y < 0 || y >= ROOM_Y*Tile.HEIGHT) {
                continue;
            }
            for (int x = x0; x <= x1; x++) {
                if (x < 0 || x >= ROOM_X*Tile.WIDTH) 
                	continue;
                RoomInterior[x + y * ROOM_X*Tile.WIDTH].addBoundingBoxToList(result, e);
            }
        }*/
        

        // Adding other entities to list
        for (Entity otherEntity : entities) {
            if (otherEntity != e && otherEntity.blocks(e)) {
                result.add(otherEntity.getBoundingBox());
            }
        }

        return result;
    }

	public void addMob(LivingEntity e)
	{
		Coordinate newPos = new Coordinate();
		
		do
		{
			newPos.x = RandNum.getRandNum(1,ROOM_X-1);
			newPos.y = RandNum.getRandNum(1,ROOM_Y-1);
		}
		while(!(RoomInterior[newPos.getX() + newPos.getY() * ROOM_X] instanceof GrassTile));
	
		newPos.x *= Tile.WIDTH;
		newPos.y *= Tile.HEIGHT;
		
		newPos.x += Tile.WIDTH/2;
		newPos.y += Tile.HEIGHT/2;
		
		
		addMob(e,newPos);
	}
	
	public void addMob(LivingEntity e, Coordinate pos)
	{
		e.setLevel(level);
		e.position = pos;
		addEntity(e);
		mobCount++;
	}

	public void setNorthDoor(boolean hasDoor)
	{
	
		if(hasNorthDoor != hasDoor)
		{
			Tile oldTile = RoomInterior[ROOM_NORTHDOOR];
			// make change in RoomInterior
			if(hasDoor)
				RoomInterior[ROOM_NORTHDOOR] = new GrassTile();
			else
				RoomInterior[ROOM_NORTHDOOR] = new WallTile();
		
			RoomInterior[ROOM_NORTHDOOR].init(oldTile.level, oldTile.position.x, oldTile.position.y);
			
			// make the boolean change
			this.hasNorthDoor = hasDoor;
			
			Teleporter tp = new Teleporter(new Coordinate(oldTile.position.x*Tile.WIDTH+Tile.WIDTH/2,oldTile.position.y*Tile.HEIGHT+Tile.HEIGHT/2-10), new Coordinate (32,10) ,true);
			tp.setLevel(oldTile.level);
			addEntity(tp);
		}

	}
	
	public void setSouthDoor(boolean hasDoor)
	{
		if(hasSouthDoor != hasDoor)
		{
			Tile oldTile = RoomInterior[ROOM_SOUTHDOOR];
			// make change in RoomInterior
			if(hasDoor)
				RoomInterior[ROOM_SOUTHDOOR] = new GrassTile();
			else
				RoomInterior[ROOM_SOUTHDOOR] = new WallTile();
		
			RoomInterior[ROOM_SOUTHDOOR].init(oldTile.level, oldTile.position.x, oldTile.position.y);
			
			// make the boolean change
			this.hasSouthDoor = hasDoor;
			
			Teleporter tp = new Teleporter(new Coordinate(oldTile.position.x*Tile.WIDTH+Tile.WIDTH/2,oldTile.position.y*Tile.HEIGHT+Tile.HEIGHT/2+10), new Coordinate (32,10) ,true);
			tp.setLevel(oldTile.level);
			addEntity(tp);
		}
	}
	
	public void setEastDoor(boolean hasDoor)
	{
		if(hasEastDoor != hasDoor)
		{
			Tile oldTile = RoomInterior[ROOM_EASTDOOR];
			// make change in RoomInterior
			if(hasDoor)
				RoomInterior[ROOM_EASTDOOR] = new GrassTile();
			else
				RoomInterior[ROOM_EASTDOOR] = new WallTile();
		
			RoomInterior[ROOM_EASTDOOR].init(oldTile.level, oldTile.position.x, oldTile.position.y);
			
			// make the boolean change
			this.hasEastDoor = hasDoor;
			
			Teleporter tp = new Teleporter(new Coordinate(oldTile.position.x*Tile.WIDTH+Tile.WIDTH/2+10,oldTile.position.y*Tile.HEIGHT+Tile.HEIGHT/2), new Coordinate (10,32) ,true);
			tp.setLevel(oldTile.level);
			addEntity(tp);
		}
	}
	
	public void setWestDoor(boolean hasDoor)
	{
		if(hasWestDoor != hasDoor)
		{
			Tile oldTile = RoomInterior[ROOM_WESTDOOR];
			// make change in RoomInterior
			if(hasDoor)
				RoomInterior[ROOM_WESTDOOR] = new GrassTile();
			else
				RoomInterior[ROOM_WESTDOOR] = new WallTile();
		
			RoomInterior[ROOM_WESTDOOR].init(oldTile.level, oldTile.position.x, oldTile.position.y);
			
			// make the boolean change
			this.hasWestDoor = hasDoor;
			
			Teleporter tp = new Teleporter(new Coordinate(oldTile.position.x*Tile.WIDTH+Tile.WIDTH/2-10,oldTile.position.y*Tile.HEIGHT+Tile.HEIGHT/2), new Coordinate (10,32) ,true);
			tp.setLevel(oldTile.level);
			addEntity(tp);
		
		}
		
	}

	public void render(Screen screen) {
		// TODO Auto-generated method stub
		screen.clearWithColor(0xff000000);
		for(Tile t:RoomInterior)
		{
			t.render(screen);
		}

		for (Entity e:entities) {
			if(!e.removed)
				e.render(screen);
		}
		
		for(Tile t:RoomInterior)
		{
			t.render2(screen);
		}

	}
	
	public void renderDebug(Screen screen)
	{
		for (Entity e:entities) {
			e.getBoundingBox().render(screen);
		}
		
	}

	

}
